import 'package:dio/dio.dart';

typedef HttpSuccessCallBack<T> = void Function(dynamic data);
typedef HttpFailCallBack = void Function(DioError err);

/// 网络请求管理
/// 1. HttpManager 设置为单利模式，便于管理网络请求
class HttpManager {
  Dio _dio;
  // 创建单利
  static final HttpManager _instance = HttpManager._internal();

  factory HttpManager() => _instance;
  HttpManager._internal() {
    if (_dio == null) {
      var options = BaseOptions(
        responseType: ResponseType.json, // 响应数据的类型`json`
      );

      _dio = Dio(options);
    }
  }

  /// 初始化
  /// 这里的 `options` 配置会覆盖掉 `HttpManager._internal()` 中的 配置。
  void configration({
    String baseUrl,
    int connectTimeout,
    int receiveTimeout,
    int sendTimeout,
    Map<String, dynamic> extra,
    Map<String, dynamic> headers,
    ResponseType responseType,
    String contentType,
    ValidateStatus validateStatus,
    bool receiveDataWhenStatusError,
    bool followRedirects,
    int maxRedirects,
    RequestEncoder requestEncoder,
    ResponseDecoder responseDecoder,
    List<Interceptor> interceptors,
  }) {
    // 初始化配置更改
    _dio.options = _dio.options.merge(
      baseUrl: baseUrl,
      connectTimeout: connectTimeout,
      receiveTimeout: receiveTimeout,
      sendTimeout: sendTimeout,
      extra: extra,
      headers: headers,
      responseType: responseType,
      contentType: contentType,
      validateStatus: validateStatus,
      receiveDataWhenStatusError: receiveDataWhenStatusError,
      followRedirects: followRedirects,
      maxRedirects: maxRedirects,
      requestEncoder: requestEncoder,
      responseDecoder: responseDecoder,
    );

    // 添加拦截器
    if (interceptors != null && interceptors.isNotEmpty) {
      _dio.interceptors.addAll(interceptors);
    }
  }

  /// 请求网络接口
  void requestBlock(
    String path, {
    String method = HttpMethod.GET,
    data,
    Map<String, dynamic> queryParameters,
    Options options,
    HttpSuccessCallBack successCallBack,
    HttpFailCallBack failCallBack,
  }) async {
    // 参数校验
    options?.method = method;
    options = options ?? Options(method: method);

    try {
      var response = await _dio.request(
        path,
        data: data,
        queryParameters: queryParameters,
        options: options,
      );

      if (successCallBack != null) successCallBack(response.data);
    } catch (e) {
      if (failCallBack != null) failCallBack(e);
    }
  }

  /// 请求网络接口
  Future<Response> requestAsync(
    String path, {
    String method = HttpMethod.GET,
    data,
    Map<String, dynamic> queryParameters,
    Options options,
  }) async {
    // 参数校验
    options?.method = method;
    options = options ?? Options(method: method);

    try {
      var response = await _dio.request(
        path,
        data: data,
        queryParameters: queryParameters,
        options: options,
      );

      return response;
    } catch (e) {
      return Future.error(e);
    }
  }

  void delHeader(String key) {
    _dio.options.headers.remove(key);
  }

  void lock() {
    _dio.interceptors.requestLock.lock();
  }

  void unlock() {
    _dio.interceptors.requestLock.unlock();
  }
}

/// 请求方式
class HttpMethod {
  static const String GET = 'get';
  static const String POST = 'post';
  static const String DELETE = 'delete';
  static const String PATCH = 'PATCH';
}

/// `Option` 默认配置
class HttpDefaultOption {
  static const int CON_TIMEOUT = 1000;
  static const int RECIVE_TIMEOUT = 1000;
  static const int SEND_TIMEOUT = 1000;
}
